package com.gx.core
{
	import com.gx.components.BitmapLayer;
	import com.gx.components.motor2.PhysicsLayerM2;
	import com.gx.data.IXMLDecoder;
	import com.gx.interfaces.IDrawable;
	import com.gx.interfaces.ILayer;
	import com.gx.interfaces.ILoader;
	import com.gx.interfaces.IPhysical;
	import com.gx.interfaces.IPhysicsLayer;
	import com.gx.components.BitmapLoader;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.PixelSnapping;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	import flash.utils.getDefinitionByName;
	import flash.utils.getTimer;
	
	public class Scene extends Sprite
	{
		private var _drawableComponents:Array = new Array();
		private var _physicsComponents:Array = new Array();
		private var _physicsWorlds:Array = new Array();
		private var _componentDict:Dictionary = new Dictionary();
		
		private var _assets:Dictionary = new Dictionary();

		public var stepSize:Number;
		public var iterations:int;
		
		public function Scene()
		{
			iterations = 30;
			stepSize = 1 / 60;
		}
		
		public function parseXML(sceneXML:XML):void
		{
			//load bitmaps
			for each(var assetXML:XML in sceneXML.assets.children())
			{
				var assetClassName:String = assetXML.name().uri + assetXML.name().localName;
				var AssetClass:Class = getDefinitionByName(assetClassName) as Class;
			
				// Instantiate the class and assign layer and world to it
				var newAsset:ILoader = new AssetClass();
				IXMLDecoder(newAsset).decode(assetXML);
				_assets[assetXML.@id] = newAsset;
				
			}
			for each(var loader:ILoader in _assets)
			{
				loader.addEventListener(Event.COMPLETE, onLoaderComplete, false, 0, true);
				loader.addEventListener(IOErrorEvent.IO_ERROR, onLoaderError, false, 0, true);
				loader.load();
			}
			
			//add layers
			for each(var layerXML:XML in sceneXML.layers.children())
			{
				var layerClassName:String = layerXML.name().uri + layerXML.name().localName;
				var LayerClass:Class = getDefinitionByName(layerClassName) as Class;
			
				// Instantiate the class and assign layer and world to it
				var newLayer:ILayer = new LayerClass();
				IXMLDecoder(newLayer).decode(layerXML);
				_layers.push(newLayer);
			}
			//load entities
		}
		
		private function onLoaderComplete(e:Event):void
		{
			
		}
		
		private function onLoaderError(e:IOErrorEvent):void
		{
			trace(e.text);
		}
		
		public function init():void
		{
			
		}


		
		public function update(dt:Number):void
		{
			this.updatePhysics();
			this.draw();

		}
		
		

		private var _layers:Array = new Array();
		public function get layers():Array {return _layers;}
		public function set layers(value:Array):void 
		{
			_layers = value;
		}
		

		private var _entities:Array = new Array();
		public function get entities():Array {return _entities;}
		public function set entities(value:Array):void 
		{
			_entities = value;
			for each(var e:Entity in _entities)
			{
				addEntity(e);
			}
		}
		
		public function addEntity(entity:Component):void
		{
			addComponent(entity);
			for each(var c:Component in entity.components)
			{
				addComponent(c);
			}
		}
		
		public function addComponent(component:Component):void
		{
			if(component is IDrawable)
			{
				_drawableComponents.push(component);
			}
			if(component is IPhysical)
			{
				_physicsComponents.push(component);
				IPhysical(component).init();
			}
			if(component is IPhysicsLayer)
			{
				_physicsWorlds.push(component);
				IPhysicsLayer(component).init();
			}
			if(component.components.length > 0)
			{
				for each(var c:Component in component.components)
				{
					addComponent(c);
				}
			}
		}
		
		public function updatePhysics():void
		{
			for each(var world:IPhysicsLayer in _physicsWorlds)
			{
				world.step(stepSize,iterations);
			}
			for each(var physical:IPhysical in _physicsComponents)
			{
				physical.update();
			}
		}
		
		public function draw():void
		{
			//this.bitmap.bitmapData.fillRect(new Rectangle(0,0,stage.width,stage.height), 0xFFFFFF);
			//for each(var drawable:IDrawable in _drawableComponents)
			//{
			//	drawable.render(bitmap);
			//}
		}
		
		


		private var _materials:Array;
		public function get materials():Array {return _materials;}
		public function set materials(value:Array):void {_materials = value;}		
		
		
		
		private var dummyBL:BitmapLayer = new BitmapLayer();
		private var dummyPL:PhysicsLayerM2 = new PhysicsLayerM2();
	}
}